<?php
/**
 * OpenOTP Authentication Drupal module
 *
 * LICENSE
 *
 * Copyright © 2013.
 * RCDevs OpenOTP. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
  
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * *
 * @copyright Copyright (c) 2013 RCDevs (http://www.rcdevs.com)
 * @author rcdevs <info@rcdevs.com>
 * @package OpenOTP-7.x
 */
/*
 * @file
 * OpenOTP implementation Class.
 */
class openotp { 

	private $ModuleDir;
	private $server_url;
	private $client_id;
	private $default_domain;
	private $client_settings;                                                                           
	private $proxy_host;                                                                              
	private $proxy_port;                                                                              
	private $proxy_username;
	private $proxy_password;
	private $soap_client;


	public function __construct($path){

        $this->ModuleDir = $path;
	}
	/**
	* Check if File exists
	*
	* @param string $file
	* @return bool
	*/
	public function checkFile($file)
	{
		if (!file_exists($this->ModuleDir . '/'.$file)) {
			return false;
		}
		return true;
	}
	
	/**
	* Check if SOAP extension loaded
	*
	* @return bool
	*/
	public function checkSOAPext()
	{
		if (!extension_loaded('soap')) {
			return false;
		}
		return true;
	}

		
	public function getDomain($username)
	{
		$pos = strpos($username, "\\");
		if ($pos) {
			$ret['domain'] = substr($username, 0, $pos);
			$ret['username'] = substr($username, $pos+1);
		} else {                                                                                                    
			$ret = $this->default_domain;
		}
		return $ret;
	}
	
	public function getOverlay($otpChallenge, $u2fChallenge, $message, $username, $session, $timeout, $ldappw, $domain){
		$path = $this->ModuleDir;
		$overlay = "";
		//Prevent "Password field is required" error msg for loginMode = OTP
		if($ldappw == NULL) $ldappw = "dummy";
		$overlay = <<<EOT
		function addOpenOTPDivs(){
			var overlay_bg = document.createElement("div");
			overlay_bg.id = 'openotp_overlay_bg';
			overlay_bg.style.position = 'fixed'; 
			overlay_bg.style.top = '0'; 
			overlay_bg.style.left = '0'; 
			overlay_bg.style.width = '100%'; 
			overlay_bg.style.height = '100%'; 
			overlay_bg.style.background = 'grey';
			overlay_bg.style.zIndex = "9998"; 
			overlay_bg.style["filter"] = "0.9";
			overlay_bg.style["-moz-opacity"] = "0.9";
			overlay_bg.style["-khtml-opacity"] = "0.9";
			overlay_bg.style["opacity"] = "0.9";
			
			var action = document.getElementById("user-login-form").getAttribute("action");
			var token = document.getElementsByName("form_build_id")[0].value;
			var overlay = document.createElement("div");
			overlay.id = 'openotp_overlay';
			overlay.style.position = 'absolute'; 
			overlay.style.top = '165px'; 
			overlay.style.left = '50%'; 
			overlay.style.width = '280px'; 
			overlay.style.marginLeft = '-180px';
			overlay.style.padding = '65px 40px 50px 40px';
			overlay.style.background = 'url($path/openotp_banner.png) no-repeat top left #E4E4E4';
			overlay.style.border = '5px solid #545454';
			overlay.style.borderRadius = '10px';
			overlay.style.MozBorderRadius = '10px';
			overlay.style.WebkitBorderRadius = '10px';
			overlay.style.boxShadow = '1px 1px 12px #555555';
			overlay.style.WebkitBoxShadow = '1px 1px 12px #555555';
			overlay.style.MozBoxShadow = '1px 1px 12px #555555';
			overlay.style.zIndex = "9999"; 
			overlay.innerHTML = '<a style="position:absolute; top:-12px; right:-12px;" href="$_SERVER[PHP_SELF]" title="close"><img src="$path/openotp_closebtn.png"/></a>'
			+ '<style>'
			+ 'blink { -webkit-animation: blink 1s steps(5, start) infinite; -moz-animation:    blink 1s steps(5, start) infinite; -o-animation:      blink 1s steps(5, start) infinite; animation: blink 1s steps(5, start) infinite; }'
			+ '	@-webkit-keyframes blink { to { visibility: hidden; } }'
			+ '@-moz-keyframes blink { to { visibility: hidden; } }'
			+ '@-o-keyframes blink { to { visibility: hidden; } }'
			+ '@keyframes blink { to { visibility: hidden; } }'
			+ '</style>'					
			+ '<div style="background-color:red; margin:0 -40px 0; height:4px; width:360px; padding:0;" id="count_red"><div style="background-color:orange; margin:0; height:4px; width:360px; padding:0;" id="div_orange"></div></div>'
			+ '<form id="user-login-form-otp" autocomplete="off" style="margin-top:30px; display:block;" action="'+action+'" method="POST">'
			+ '<input type="hidden" name="form_build_id" value="'+token+'">'
            + '<input type="hidden" id="edit-name" name="name" value="$username">'
            + '<input type="hidden" id="edit-pass" name="pass" value="$ldappw" />'			
			+ '<input type="hidden" name="openotp_state" value="$session">'
			+ '<input type="hidden" name="openotp_domain" value="$domain">'
			+ '<input type="hidden" value="user_login_block" name="form_id">'
			+ '<table style="border-collapse:inherit; margin:0;" width="100%">'
			+ '<tr style="background:none"><td style="text-align:center; font-weight:bold; font-size:14px; border:none; padding:0;">$message</td></tr>'
			+ '<tr style="background:none"><td id="timout_cell" style="text-align:center; padding-top:4px; font-weight:bold; font-style:italic; font-size:11px; border:none;">Timeout: <span id="timeout">$timeout seconds</span></td></tr>'
EOT;
			if( $otpChallenge || ( !$otpChallenge && !$u2fChallenge ) ){
				$overlay .= "+ '<tr style=\"background:none\"><td id=\"inputs_cell\" style=\"text-align:center; padding-top:25px; border:none;\"><input id=\"openotp_password\" class=\"form-text required\" type=\"text\" size=15 name=\"openotp_password\">&nbsp;'";
				$overlay .= "+ '<input style=\"padding:3px 10px;\" type=\"submit\" value=\"Ok\" class=\"form-submit\"></td></tr>'";
			}
			
			if( $u2fChallenge ){		
			$overlay .= "+ '<tr style=\"border:none; background:none\"><td id=\"inputs_cell\" style=\"text-align:center; padding-top:5px; border:none;\"><input type=\"hidden\" name=\"openotp_u2f\" value=\"\">'";
				if( $otpChallenge ){		
					$overlay .= "+ '<b>U2F response</b> &nbsp; <blink id=\"u2f_activate\">[Activate Device]</blink></td></tr>'";
				} else { 
					$overlay .= "+ '<img src=\"" . $path . "/u2f.png\"><br><br><blink id=\"u2f_activate\">[Activate Device]</blink></td></tr>'";
				}			
			}		
			$overlay .=<<<EOT
			+ '</table></form>';
			
				document.body.appendChild(overlay_bg);    
				document.body.appendChild(overlay); 
		}
		
		
		/* Compute Timeout */	
		var c = $timeout;
		var base = $timeout;
		function count()
		{
			plural = c <= 1 ? "" : "s";
			document.getElementById("timeout").innerHTML = c + " second" + plural;
			var div_width = 360;
			var new_width =  Math.round(c*div_width/base);
			jQuery("#div_orange").animate({
				width: new_width+'px',
				}, 1000 );
			
			if( document.getElementById('openotp_password') ){
				document.getElementById('openotp_password').focus();
			}
			
			if(c == 0 || c < 0) {
				c = 0;
				clearInterval(timer);
				document.getElementById("timout_cell").innerHTML = " <b style='color:red;'>Login timedout!</b> ";
				document.getElementById("inputs_cell").innerHTML = "<input style='padding:3px 20px;' type='button' value='Retry' class='form-submit' onclick='window.location.href=\"$_SERVER[PHP_SELF]\"'>";
			}
			c--;
		}
		function getInternetExplorerVersion() {
		
			var rv = -1;
		
			if (navigator.appName == "Microsoft Internet Explorer") {
				var ua = navigator.userAgent;
				var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
				if (re.exec(ua) != null)
					rv = parseFloat(RegExp.$1);
			}
			return rv;
		}
		
		var ver = getInternetExplorerVersion();
		
		
				
		var timer = setInterval(function() {count(); }, 1000);			
		
		jQuery(document).ready(function() {
			addOpenOTPDivs();
			jQuery("#messages .messages.error").hide();
			count();
			
			if (navigator.appName == "Microsoft Internet Explorer"){
				if (ver <= 10){
					toggleItem = function(){
					
					    var el = document.getElementsByTagName("blink")[0];
					    if (el.style.display === "block") {
					        el.style.display = "none";
					    } else {
					        el.style.display = "block";
					    }
					}
					var t = setInterval(function() {toggleItem; }, 1000);
				}
			}			
		});
		
		
EOT;

		if( $u2fChallenge ) $overlay .= "jQuery(document).ready(function() { if (typeof u2f !== 'object' || typeof u2f.sign !== 'function'){ var u2f_activate = document.getElementById('u2f_activate'); u2f_activate.innerHTML = '[Not Supported]'; u2f_activate.style.color='red'; }" . "\r\n";
		if( $u2fChallenge ) $overlay .= " else {  u2f.sign([".$u2fChallenge."], function(response) { document.getElementsByName('openotp_u2f')[0].value = JSON.stringify(response); document.getElementById('user-login-form-otp').submit(); }, $timeout ); } });" . "\r\n";
		
		return $overlay;
	}
	
	private function soapRequest(){

		$options = array('location' => $this->server_url);
		if ($this->proxy_host != NULL && $this->proxy_port != NULL) {
			$options['proxy_host'] = $this->proxy_host;
			$options['proxy_port'] = $this->proxy_port;
			if ($this->proxy_username != NULL && $this->proxy_password != NULL) {
				$options['proxy_login'] = $this->proxy_username;
				$options['proxy_password'] = $this->proxy_password;
			}
		}
			
		$soap_client = new SoapClient($this->ModuleDir.'/openotp.wsdl', $options);
		if (!$soap_client) {
			return false;
		}
		$this->soap_client = $soap_client;	
		return true;
	}
		
	public function openOTPSimpleLogin($username, $domain, $password, $remote_add){
		if (!$this->soapRequest()) return false;
		$resp = $this->soap_client->openotpSimpleLogin($username, $domain, $password, $this->client_id, $remote_add, $this->client_settings);

		return $resp;
	}
	
	public function openOTPChallenge($username, $domain, $state, $password, $u2f){
		if (!$this->soapRequest()) return false;
		$resp = $this->soap_client->openotpChallenge($username, $domain, $state, $password, $u2f);
		
		return $resp;
	}
	
	public function setEtcModuleDir($dir)
	{
		$this->ModuleDir = $dir;
	}
	
	public function setServer_url($server_url)
	{
		$this->server_url = $server_url;
	}

	public function getServer_url()
	{
		return $this->server_url;
	}

	public function setClient_id($client_id)
	{
		$this->client_id = $client_id;
	}

	public function getClient_id()
	{
		return $this->client_id;
	}

	public function setDefault_domain($default_domain)
	{
		$this->default_domain = $default_domain;
	}

	public function getDefault_domain()
	{
		return $this->default_domain;
	}

	public function setClient_settings($client_settings)
	{
		$this->client_settings = $client_settings;
	}

	public function getClient_settings()
	{
		return $this->client_settings;
	}
	
	public function setProxy_host($proxy_host)
	{
		$this->proxy_host = $proxy_host;
	}

	public function getProxy_host()
	{
		return $this->proxy_host;
	}

	public function setProxy_port($proxy_port)
	{
		$this->proxy_port = $proxy_port;
	}

	public function getProxy_port()
	{
		return $this->proxy_port;
	}
	
	public function setProxy_login($proxy_login)
	{
		$this->proxy_login = $proxy_login;
	}

	public function getProxy_login()
	{
		return $this->proxy_login;
	}
	
	public function setProxy_password($proxy_password)
	{
		$this->proxy_password = $proxy_password;
	}

	public function getProxy_password()
	{
		return $this->proxy_password;
	}
}

?>